﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using HandyControl.Data;
using Microsoft.EntityFrameworkCore;
using OpenAiClient.Events;
using OpenAiClient.Models;
using OpenAiClient.Repositories;
using OpenAiClient.Services;
using OpenAiClient.Tools;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using MessageBox = HandyControl.Controls.MessageBox;

namespace OpenAiClient.ViewModels
{
    internal class HistoryViewModel : BindableBase
    {
        public DelegateCommand<FunctionEventArgs<int>> PageUpdatedCommand { get; }
        public DelegateCommand QueryHistoryCommand { get; }
        public DelegateCommand ClearItemsCommand { get; }

        public ObservableCollection<HistoryDto> HistoryList { get; }

        public DateTime StartDate
        {
            get => _startDate;
            set => SetProperty(ref _startDate, value);
        }

        public DateTime EndDate
        {
            get => _endDate;
            set => SetProperty(ref _endDate, value);
        }

        public int SelectedItemIndex
        {
            get => _selectedItemIndex;
            set => SetProperty(ref _selectedItemIndex, value);
        }

        public int MaxPageCount
        {
            get => _maxPageCount;
            set => SetProperty(ref _maxPageCount, value);
        }

        public int PageIndex
        {
            get => _pageIndex;
            set => SetProperty(ref _pageIndex, value);
        }

        private DateTime _startDate; //开始日期
        private DateTime _endDate; //结束日期
        private int _selectedItemIndex;
        private int _maxPageCount; //总页数
        private int _pageIndex; //页索引
        private int _count; //总个数

        private readonly ILogService _logService;
        private readonly IRepository<HistoryModel> _historyRepository;
        private readonly IEventAggregator _eventAggregator;

        public HistoryViewModel(
            ILogService logService,
            IRepository<HistoryModel> historyRepository,
            IEventAggregator eventAggregator
        )
        {
            _logService = logService;
            _historyRepository = historyRepository;
            _eventAggregator = eventAggregator;

            PageUpdatedCommand = new DelegateCommand<FunctionEventArgs<int>>(OnPageUpdatedAsync);
            QueryHistoryCommand = new DelegateCommand(OnQueryHistoryAsync);
            ClearItemsCommand = new DelegateCommand(OnClearItemsAsync);

            HistoryList = new ObservableCollection<HistoryDto>();
            StartDate = DateTime.Now.AddMonths(-1);
            EndDate = DateTime.Now;
        }

        public async Task ResetAsync()
        {
            var startDate = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, 0, 0, 0);
            var stopDate = new DateTime(EndDate.Year, EndDate.Month, EndDate.Day, 23, 59, 59);

            _count = 0;

            if (_historyRepository.DbContext.HistoryModels != null)
            {
                try
                {
                    _count = await _historyRepository.DbContext.HistoryModels
                        .Where(t => DateTime.Compare(t.CreateTime, startDate) >= 0 &&
                                    DateTime.Compare(t.CreateTime, stopDate) <= 0)
                        .CountAsync();
                }
                catch (Exception e)
                {
                    _logService.Error($"获取历史记录个数失败：{e.Message}");
                }
            }

            var maxPageCount = _count / Constants.NumberPerPage;
            maxPageCount += _count % Constants.NumberPerPage > 0 ? 1 : 0;
            maxPageCount = Math.Max(maxPageCount, 1); //最小为1
            MaxPageCount = maxPageCount;
            PageIndex = 1;

            await GetModelListAsync();
        }

        private async void OnPageUpdatedAsync(FunctionEventArgs<int> info)
        {
            PageIndex = info.Info;
            await GetModelListAsync();
        }

        private async void OnQueryHistoryAsync()
        {
            await ResetAsync();
        }

        private async void OnClearItemsAsync()
        {
            await Task.CompletedTask;

            if (MessageBox.Ask("确认删除所有记录吗", @"警告") != MessageBoxResult.OK)
            {
                return;
            }

            if (_historyRepository.DbContext.HistoryModels == null)
            {
                return;
            }

            try
            {
                while (true)
                {
                    var models = await _historyRepository.DbContext.HistoryModels
                        .Take(Constants.NumberPerPage)
                        .ToListAsync();
                    if (!models.Any())
                    {
                        break;
                    }

                    _historyRepository.DbContext.HistoryModels.RemoveRange(models);
                    await _historyRepository.DbContext.SaveChangesAsync();
                }
            }
            catch (Exception e)
            {
                var errorMessage = $"删除数据库记录失败：{e.Message}";
                _logService.Error(errorMessage);
                _eventAggregator.GetEvent<ShowGrowlSuccessEvent>().Publish(errorMessage);
                return;
            }

            SelectedItemIndex = -1;
            HistoryList.Clear();
        }

        private async Task GetModelListAsync()
        {
            HistoryList.Clear();

            if (_historyRepository.DbContext.HistoryModels == null)
            {
                return;
            }

            if (DateTime.Compare(StartDate, EndDate) >= 0)
            {
                _eventAggregator.GetEvent<ShowGrowlSuccessEvent>().Publish("查询时间有误，请检查");
                return;
            }

            var startDate = new DateTime(StartDate.Year, StartDate.Month, StartDate.Day, 0, 0, 0);
            var stopDate = new DateTime(EndDate.Year, EndDate.Month, EndDate.Day, 23, 59, 59);

            var skipCount = Constants.NumberPerPage * (PageIndex - 1);
            var modelList = await _historyRepository.DbContext.HistoryModels
                .OrderByDescending(t => t.CreateTime)
                .Where(t => DateTime.Compare(t.CreateTime, startDate) >= 0 &&
                            DateTime.Compare(t.CreateTime, stopDate) <= 0)
                .Skip(skipCount)
                .Take(Constants.NumberPerPage)
                .ToListAsync();
            if (!modelList.Any())
            {
                return;
            }

            var dtoList = modelList.Select(t => new HistoryDto(t)).ToList();
            dtoList.ForEach(t =>
            {
                t.Index = ++skipCount;
                t.OnCopyQuestion += OnCopyQuestion;
                t.OnCopyAnswer += OnCopyAnswer;
                t.OnDeleteItem += OnDeleteItem;
            });

            HistoryList.Clear();
            HistoryList.AddRange(dtoList);
        }

        private void OnCopyQuestion(HistoryDto dto)
        {
            Clipboard.SetDataObject(dto.Question ?? string.Empty, true);
            _eventAggregator.GetEvent<ShowGrowlSuccessEvent>().Publish("问题已拷贝到剪切板");
        }

        private void OnCopyAnswer(HistoryDto dto)
        {
            Clipboard.SetDataObject(dto.Answer ?? string.Empty, true);
            _eventAggregator.GetEvent<ShowGrowlSuccessEvent>().Publish("答案已拷贝到剪切板");
        }

        private async void OnDeleteItem(HistoryDto dto)
        {
            var message = $"确认删除该项[{dto.Question}]？";
            if (MessageBox.Ask(message, @"询问") != MessageBoxResult.OK)
            {
                return;
            }

            if (_historyRepository.DbContext.HistoryModels == null)
            {
                return;
            }

            try
            {
                var model = await _historyRepository.DbContext.HistoryModels
                    .SingleAsync(t => t.Id == dto.Id);
                _historyRepository.DbContext.HistoryModels.Remove(model);
                await _historyRepository.DbContext.SaveChangesAsync();
            }
            catch (Exception e)
            {
                var errorMessage = $"数据库操作失败：{e.Message}";
                _logService.Error(errorMessage);
                _eventAggregator.GetEvent<ShowGrowlSuccessEvent>().Publish(errorMessage);
                return;
            }

            SelectedItemIndex = -1;
            HistoryList.Remove(dto);
        }
    }
}
